package com.tuling.vipes.service.impl;


import com.tuling.vipes.bean.Product;
import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.metrics.Avg;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Service
public class SearchService {

    @Autowired
    private RestHighLevelClient client;

    // 查询
    public List<Product> search(String keyword) throws IOException {
        SearchRequest searchRequest = new SearchRequest("products_demo");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        // 匹配查询
        MatchQueryBuilder matchQuery = QueryBuilders.matchQuery("name", keyword);
        sourceBuilder.query(matchQuery);

        // 高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("name");
        sourceBuilder.highlighter(highlightBuilder);


        // 聚合：按 category 分组
        sourceBuilder.aggregation(AggregationBuilders.terms("by_category").field("category.keyword"));

        // 排序：按 price 升序排序
        sourceBuilder.sort("price", SortOrder.ASC);

        searchRequest.source(sourceBuilder);
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);

        return parseResponse(response);
    }

    // 内嵌查询
    public List<Product> nestedSearch(String category) throws IOException {
        SearchRequest searchRequest = new SearchRequest("products_demo");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        // 内嵌查询
        NestedQueryBuilder nestedQuery = QueryBuilders.nestedQuery("category",
                QueryBuilders.matchQuery("category.name", category), ScoreMode.None);
        sourceBuilder.query(nestedQuery);

        searchRequest.source(sourceBuilder);
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);

        return parseResponse(response);
    }

    // 范围查询
    public List<Product> rangeSearch(double minPrice, double maxPrice) throws IOException {
        SearchRequest searchRequest = new SearchRequest("products_demo");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        // 范围查询
        RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("price").gte(minPrice).lte(maxPrice);
        sourceBuilder.query(rangeQuery);

        searchRequest.source(sourceBuilder);
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);

        return parseResponse(response);
    }

    // 聚合查询
    public void aggregateSearch() throws IOException {
        SearchRequest searchRequest = new SearchRequest("products_demo");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        // 按类别聚合
        sourceBuilder.aggregation(AggregationBuilders.terms("by_category").field("category.keyword"));
        // 子集聚合：计算每个类别的平均价格
        sourceBuilder.aggregation(AggregationBuilders.avg("avg_price").field("price"));

        searchRequest.source(sourceBuilder);
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);

        // 解析聚合结果
        Terms terms = response.getAggregations().get("by_category");
        for (Terms.Bucket bucket : terms.getBuckets()) {
            System.out.println("Category: " + bucket.getKeyAsString() + ", Count: " + bucket.getDocCount());
            Avg avg = bucket.getAggregations().get("avg_price");
            System.out.println("Average Price: " + avg.getValue());
        }
    }

    // 排序
    public List<Product> sortSearch(String field, SortOrder order) throws IOException {
        SearchRequest searchRequest = new SearchRequest("products_demo");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        // 排序
        sourceBuilder.sort(field, order);

        searchRequest.source(sourceBuilder);
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);

        return parseResponse(response);
    }

    // 解析响应
    private List<Product> parseResponse(SearchResponse response) {
        List<Product> products = new ArrayList<>();
        response.getHits().forEach(hit -> {
            Product product = new Product();
            product.setId(hit.getId());
            product.setName(hit.getSourceAsMap().get("name").toString());
            product.setDescription(hit.getSourceAsMap().get("description").toString());
            product.setPrice(Double.parseDouble(hit.getSourceAsMap().get("price").toString()));
            product.setCategory(hit.getSourceAsMap().get("category").toString());
            products.add(product);
        });
        return products;
    }


    // 周边查询
    public List<Product> geoDistanceSearch(double lat, double lon, String distance) throws IOException {
        SearchRequest searchRequest = new SearchRequest("products_demo");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        // 地理距离查询
        GeoDistanceQueryBuilder geoQuery = QueryBuilders.geoDistanceQuery("location")
                .point(lat, lon)
                .distance(distance);
        sourceBuilder.query(geoQuery);

        searchRequest.source(sourceBuilder);
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);

        return parseResponse(response);
    }

    // 内嵌类型查询
    public List<Product> nestedDetailSearch(String key, String value) throws IOException {
        SearchRequest searchRequest = new SearchRequest("products_demo");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        // 内嵌类型查询
        NestedQueryBuilder nestedQuery = QueryBuilders.nestedQuery("details",
                QueryBuilders.boolQuery()
                        .must(QueryBuilders.matchQuery("details.key", key))
                        .must(QueryBuilders.matchQuery("details.value", value)), ScoreMode.None);
        sourceBuilder.query(nestedQuery);

        searchRequest.source(sourceBuilder);
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);

        return parseResponse(response);
    }
}